home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / editors / unite16.zip / UNITE.C < prev    next >
C/C++ Source or Header  |  1996-02-27  |  13KB  |  373 lines

  1. /*
  2.             ╔════════════════════════════════════════╗
  3.             ║                UNITE!                  ║
  4.             ║   Copyright (c) 1994-96 L.I.Williams   ║
  5.             ║          All rights reserved           ║
  6.             ║   Issue 1.6             Date: 27Feb96  ║
  7.             ╚════════════════════════════════════════╝
  8. *~
  9. *~    UNITE.C
  10. *~    Join 2 files outputting lines the same and the differences
  11. *~    If you modify/improve this source, I appreciate a note
  12. *~
  13. */
  14. /***********************************************************************
  15. * HISTORY:
  16. * Date      Iss  Who Comment
  17. * 17-JAN-88 1.0  LIW Created
  18. * 24-AUG-89 1.1  LIW ### End difference added
  19. * 13-DEC-93 1.2  LIW Rename to UNITE
  20. * 12-FEB-94 1.3  LIW Remove free message
  21. * 06-OCT-95 1.5  LIW Format for freeware release
  22. * 20-FEB-96 1.6  LIW Add VENDOR.DOC
  23. ***********************************************************************/
  24. /* standard routines */
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include <string.h>
  28.  
  29. /* constants */
  30. #define TRUE 1
  31. #define FALSE 0
  32. /* This module declares the global variables: */
  33. char    ext[40];        /* holds a file name extension */
  34. char    *s1,
  35.     *s2;            /* handy pointers */
  36. char
  37.     prog1[100][192],    /* 100 line buffer for 1st file */
  38.     prog2[100][192],    /* 100 line buffer for 2nd file */
  39.     inpnam1[40],        /* 1st file name store */    
  40.     inpnam2[40];        /* 2nd file name store */
  41. int
  42.     debug,            /* TRUE = lots of debug printout */
  43.     i,
  44.     first1,            /* File1:1st line at which a match is found */
  45.     curr1,            /* File1 the current line being matched */
  46.     beyond1,        /* File1 1 beyond the end of the buffer */
  47.     first2,            /* File2:1st line at which a match is found */
  48.     curr2,            /* File2 the current line being matched */
  49.     beyond2,        /* File2 1 beyond the end of the buffer */
  50.     match;            /* no of lines matched at this point */
  51. char    c;
  52. FILE    *inpfil1;        /* 1st file specified */
  53. FILE    *inpfil2;        /* 2nd file specified */
  54.  
  55. /***********************************************************************
  56. * Debug print routines. These routines only print if /d is specified
  57. * e.g. UNITE FRED1 FRED2 /d > FRED.UNI
  58. * Start of code.
  59. ***********************************************************************/
  60. tprintf (args1)
  61. char    *args1;
  62. {
  63. if (debug) 
  64.   printf (args1);
  65. }
  66. tprintf1 (args1,val1)
  67. char    *args1;
  68. int    val1;
  69. {
  70. if (debug) 
  71.   printf (args1,val1);
  72. }
  73. tprintf2 (args1,val1,val2)
  74. char    *args1;
  75. int    val1;
  76. int    val2;
  77. {
  78. if (debug) 
  79.   printf (args1,val1,val2);
  80. }
  81.  
  82. /***********************************************************************
  83. * Explains parameters etc. 
  84. ***********************************************************************/
  85. void explain()
  86. {
  87. printf("\n\
  88.             ╔════════════════════════════════════════╗\n\
  89.             ║                UNITE!                  ║\n\
  90.             ║   Copyright (c) 1994-96 L.I.Williams   ║\n\
  91.             ║          All rights reserved           ║\n\
  92.             ║   Issue 1.6             Date: 20Feb96  ║\n\
  93.             ╚════════════════════════════════════════╝\n\
  94. ");
  95. printf("\n\UNITE joins or merges two somewhat different versions of the same\n");
  96. printf("text file together. It does a file compare in which the lines that\n");
  97. printf("are the same are output, as well as the differences, which are\n");
  98. printf("highlighted with '### <filename>.' \n");
  99. printf("\n");
  100. printf("Example:  UNITE CONFIG.SYS CONFIG.OLD > CONFIG.JOI\n");
  101. printf("\n");
  102. printf("\
  103. will combine together two versions of CONFIG.SYS in the current directory\n\
  104. and output the combination with the differences highlighted to file\n\
  105. CONFIG.JOI. UNITE is freeware. Send problems, comments, suggestions,\n\
  106. appreciative notes, and requests to be kept up-to-date with issues, to:\n\
  107. Lewis Williams, 100103.2675@compuserve.com. If you like this program, take a\n\
  108. look at UPCOPY, my bi-directional directory synchronizer. If your gratitude\n\
  109. for it knows no bounds you could register that instead for $25!\n\
  110. ");
  111. }
  112.  
  113. /***********************************************************************
  114. * Subroutine to open files etc.
  115. ***********************************************************************/
  116. int openfils(argc,argv)
  117. int argc;
  118. char *argv[];    /* array of strings */
  119. {
  120. /* Take care of inpfil1 and add defaults if necessary */
  121. switch (argc)
  122.   {
  123.   default:
  124.     fprintf(stderr,"Bad parameters\n");
  125.     return TRUE;
  126.   case 1:
  127.     explain();
  128.     return TRUE;
  129.   case 2:
  130.     strcpy(inpnam1,argv[1]);
  131.     strcpy(inpnam2,"*.bak");    /* default to <filename>.bak if no 2nd file */
  132.     break;
  133.   case 3:
  134.     strcpy(inpnam1,argv[1]);    /* copy both filenames */
  135.     strcpy(inpnam2,argv[2]);
  136.     break;
  137.   case 4:
  138.     strcpy(inpnam1,argv[1]);
  139.     strcpy(inpnam2,argv[2]);
  140.     debug = !(strncmp("/d",argv[3],2));    /* turn on debug facility */
  141.     break;
  142.   }
  143. if ((inpfil1 = fopen(inpnam1,"r")) == NULL)
  144.   {
  145.   fprintf(stderr,"Failed to open input file %s \n",inpnam1);
  146.   return TRUE;
  147.   }
  148. strcpy(ext,"");            /* preset NULL extension */
  149. /* deal with *.something in 2nd name */
  150. if (inpnam2[0]=='*')        /* 2nd base name is wildcard? */
  151.   {
  152.   if (inpnam2[1]=='.')
  153.     strcpy(ext,&inpnam2[1]);    /* 2nd extension */
  154.   strcpy(inpnam2,inpnam1);    /* use input name basically */
  155.   s2 = strchr(inpnam2,'.');    /* pointer to . character=remove 1st extension*/
  156.   strcpy(s2,ext);        /* add 2nd extension nsion to input name */
  157.   }
  158. /* deal with something.* in 2nd name */
  159. s2 = strchr (inpnam2,'.');    /* pointer to new . character */
  160. if (s2[1]=='*')            /* wildcard extension */
  161.   {
  162.   s1 = strchr(inpnam1,'.');    /* . character in 1st name */
  163.   strcpy(s2,s1);
  164.   }
  165. if ((inpfil2 = fopen(inpnam2,"r")) == NULL)
  166.   {
  167.   fprintf(stderr,"Failed to open input file %s \n",inpnam2);
  168.   return TRUE;
  169.   }
  170. return FALSE;            /* all is OK */
  171. }
  172.  
  173. /***********************************************************************
  174. * Typeout the lines after a match is found
  175. ***********************************************************************/
  176. void typeout()
  177. {
  178. if (debug)
  179.   printf("first1=%d,first2=%d,curr1=%d,curr2=%d,beyond1=%d,beyond2=%d,match=%d\n",first1,first2,curr1,curr2,beyond1,beyond2,match);
  180. if ((first1 == first2) && (first1 == 0) && (match != 0))
  181.   /* Files are the same. some lines to type out */
  182.   printf("%s",prog1[0]);
  183. else
  184.   /* files are different */
  185.   /* output lines from file 1 */
  186.   {
  187.   if (match)
  188.     {
  189.     first1--;            /* backup to non-matching lines */
  190.     first2--;
  191.     }
  192.   if (first1>=0)
  193.     printf("### %s\n",inpnam1);    /* header if required */
  194.   for (i=0;i<=first1;i++)
  195.     printf("%s",prog1[i]);
  196.   if (first2 >= 0)
  197.     printf("### %s\n",inpnam2);    /* header as required */
  198.   for (i=0;i<=first2;i++)
  199.     printf("%s",prog2[i]);
  200.   if ((first1 >= 0) || (first2 >= 0))
  201.     printf("### End difference\n");        /* footer as required */
  202.   }
  203. /* Copy data in buffers back to the beginning */
  204. tprintf2("Copying lines %d to %d down in file1\n",first1+1,beyond1-1);
  205. for (i=first1+1;i<=beyond1-1;i++)
  206.   strcpy(prog1[i-first1-1],prog1[i]);
  207. tprintf2("Copying lines %d to %d down in file2\n",first2+1,beyond2-1);
  208. for (i=first2+1;i<=beyond2-1;i++)
  209.   strcpy(prog2[i-first2-1],prog2[i]);
  210. curr1 = -1;                /* set startup situation */
  211. curr2 = -1;
  212. beyond1 = beyond1  - first1 - 1;
  213. beyond2 = beyond2 - first2 - 1;
  214. first1 = 0;
  215. first2 = 0;
  216. if (debug)
  217.   {
  218.   printf("Setting beyond1 = %d and beyond2 = %d\n",beyond1,beyond2);
  219.   printf("Setting curr1 and curr2 to -1\n");
  220.   printf("Setting first1,first2\n");
  221.   }
  222. }
  223.  
  224. /***********************************************************************
  225. * Get next line from file1 or buffer1
  226. ***********************************************************************/
  227. int getlin1()
  228. {
  229. curr1++;            /* point to next line */
  230. tprintf1("Inc'd curr1 to %d\n",curr1);
  231. if (curr1 >= beyond1)        /* 1st buffer is used up */
  232.   {
  233.   tprintf2("First buffer is used up - reading a line curr1 = %d, beyond1 = %d\n",curr1,beyond1);
  234.   if (fgets(prog1[curr1],128,inpfil1)==NULL)    /* end of file 1 */
  235.     {
  236.     curr1 = beyond1 - 1;        /* set line to last available */
  237.     tprintf1("File1 is exhausted. Reset curr1 to beyond1 -1 (%d)\n",curr1);
  238.     return TRUE;            /* failed to get line */
  239.     }
  240.   beyond1++;        /* one more line in buffer 1 */
  241.   tprintf1("Incrementing beyond1 to %d\n",beyond1);
  242.   if (beyond1 == 99)        /* buffer is full */
  243.     {
  244.     tprintf("### Files are too different - union aborted\n");
  245.     return TRUE;        /* failed to get line */
  246.     }
  247.   }
  248. return FALSE;            /* got line OK */
  249. }
  250.  
  251. /***********************************************************************
  252. * Get next line from file2 or buffer2
  253. ***********************************************************************/
  254. int getlin2()
  255. {
  256. curr2++;        /* point to next line */
  257. tprintf1("Inc'd curr2 to %d\n",curr2);
  258. if (curr2 >= beyond2)    /* 2nd buffer is used up */
  259.   {
  260.   tprintf("2nd buffer is used up\n");
  261.   if (beyond2 == 99)    /* buffer is full */
  262.     {
  263.     curr2 = beyond2 - 1;    /* last line available */
  264.     tprintf1("Breaking - buff2 is full\nSet curr2 to beyond2 -1 (%d)\n",curr2);
  265.     return TRUE;        /* failed to get line */
  266.     }
  267.   tprintf2("Reading a line curr2 = %d, beyond2 = %d\n",curr2,beyond2);
  268.   if (fgets(prog2[curr2],128,inpfil2)==NULL)    /* end of file 2 */
  269.     {
  270.     curr2 = beyond2 - 1;    /* last line available */
  271.     tprintf1("Returning - no more lines in file2. Reset curr2 to beyond2-1 (%d)\n",curr2);
  272.     return TRUE;        /* failed to get line */
  273.     }
  274.   beyond2++;            /* one more line in buffer 2 */
  275.   tprintf1("Incrementing beyond2 to %d\n",beyond2);
  276.   }
  277. return FALSE;            /* got line OK */
  278. }
  279.  
  280. /***********************************************************************
  281. * Main program
  282. ***********************************************************************/
  283. void main(argc,argv)
  284. int argc;
  285. char *argv[];    /* array of strings */
  286. {
  287. /* open the input files */
  288. if (openfils(argc,argv))
  289.   exit(0);            /* if an error */
  290.  
  291. /* Setup variables */
  292. first1 = 0;
  293. beyond1 = 0;
  294. first2 = 0;
  295. beyond2 = 0;
  296. curr1 = -1;
  297. curr2 = -1;
  298. match = 4;            /* preset files in synch */
  299.  
  300. for (;;)            /* infinite loop, all lines in file 1 */
  301.   {
  302.   tprintf1("Next time in file1 loop - curr1 = %d\n",curr1);
  303.   if (getlin1())        /* no more lines in file1 */
  304.     {
  305.     first1 = beyond1 -1;    /* force tidy up type out */
  306.     first2 = beyond2 -1;
  307.     tprintf2("Setting first1 = beyond1 -1 (%d) first2 = beyond2-1 (%d)\n",first1,first2);
  308.     match = 0;            /* force full typeout */
  309.     typeout();
  310.     return;
  311.     }
  312.   for (;;)            /* all lines in file2 */
  313.     {
  314.     if (getlin2())        /* no more room or something in buffer2 */
  315.       {
  316.       curr2 = -1;        /* try next line in file 1 */
  317.       tprintf("Set curr2 -1 breaking inner loop\n");
  318.       break;            /* to next line in file1 */
  319.       }
  320.     if (strcmp(prog1[curr1],prog2[curr2])==0)    /* lines the same ? */
  321.       {
  322.       if (debug)
  323.         {
  324.         printf("Lines %d and %d are the same\n",curr1,curr2);
  325.         printf("Setting first1 = curr1 (%d)\n",curr1);
  326.         printf("Setting first2 = curr2 (%d)\n",curr2);
  327.         }
  328.       first1 = curr1;            /* save this position */
  329.       first2 = curr2;
  330.       if (!match)            /* files were not in sync */
  331.         for (match=1;match <= 3;match++) /* look for 3 lines the same */
  332.           {
  333.           if (getlin1())
  334.             {
  335.             tprintf("Breaking 'cos run out of lines to match in file1\n");
  336.             break;
  337.             }
  338.           if (getlin2())
  339.             {
  340.             tprintf("Breaking 'cos run out of lines to match in file2\n");
  341.             break;
  342.            }
  343.          if (strcmp(prog1[curr1],prog2[curr2]))    /* lines same ? */
  344.            {
  345.            tprintf("Read ahead shows lines different\nJumping to inner\nSetting match 0\n");
  346.            match = 0;                /* no, try next file2 line */
  347.            goto inner;
  348.            }
  349.          else
  350.            tprintf2("Lines %d and %d are the same\n",curr1,curr2);
  351.          }                    /* end of match loop */
  352.       tprintf1("match is %d - calling typeout\n",match);
  353.       typeout();                /* typeout usually 1 line */
  354.       tprintf("Jumping to outer loop\n");
  355.       goto outer;
  356.       }
  357.     else
  358.       {
  359.       tprintf2("Lines %d and %d are different\nSetting match 0\n",curr1,curr2);
  360.       match = 0;            /* files not in synch here */
  361.       }
  362. inner:;
  363.     }                    /* end of inner loop */
  364. outer:;
  365.   }
  366. /* close the files */
  367. fclose (inpfil1);
  368. fclose (inpfil2);
  369. }
  370. /***********************************************************************
  371. * End of code
  372. ***********************************************************************/
  373.